package com.centurylink.cloud.sdk.server.services.dsl.domain.statistics.monitoring.grouping;
import com.centurylink.cloud.sdk.server.services.client.domain.group.DiskUsageMetadata;
import com.centurylink.cloud.sdk.server.services.client.domain.group.GuestUsageMetadata;
import com.centurylink.cloud.sdk.server.services.client.domain.group.SamplingEntry;
import com.centurylink.cloud.sdk.server.services.client.domain.group.ServerMonitoringStatistics;
import com.centurylink.cloud.sdk.server.services.dsl.domain.group.refs.Group;
import com.centurylink.cloud.sdk.server.services.dsl.domain.statistics.monitoring.DiskUsage;
import com.centurylink.cloud.sdk.server.services.dsl.domain.statistics.monitoring.GuestUsage;
import com.centurylink.cloud.sdk.server.services.dsl.domain.statistics.monitoring.MonitoringEntry;
import com.centurylink.cloud.sdk.server.services.dsl.domain.statistics.monitoring.MonitoringStatsEntry;
import com.centurylink.cloud.sdk.server.services.dsl.domain.statistics.monitoring.filter.MonitoringStatsFilter;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;
import java.util.stream.Stream;
import static com.centurylink.cloud.sdk.core.function.Streams.map;
import static com.centurylink.cloud.sdk.core.preconditions.Preconditions.checkNotNull;
import static java.util.stream.Collectors.summingDouble;
import static java.util.stream.Collectors.summingInt;
import static java.util.stream.Collectors.toList;
public abstract class GroupMonitoringStatsBy {
protected MonitoringStatsFilter statsFilter;
public GroupMonitoringStatsBy(MonitoringStatsFilter statsFilter) {
checkNotNull(statsFilter, "Filter must be not a null");
this.statsFilter = statsFilter;
}
public abstract List<MonitoringStatsEntry> group(Map<Group, List<ServerMonitoringStatistics>> monitoringStats);
protected List<MonitoringEntry> convertEntry(List<SamplingEntry> entries) {
return
map(entries, entry ->
new MonitoringEntry()
.timestamp(entry.getTimestamp())
.cpu(entry.getCpu())
.cpuPercent(entry.getCpuPercent())
.diskUsageTotalCapacityMB(entry.getDiskUsageTotalCapacityMB())
.memoryMB(entry.getMemoryMB())
.memoryPercent(entry.getMemoryPercent())
.networkReceivedKBps(entry.getNetworkReceivedKbps())
.networkTransmittedKBps(entry.getNetworkTransmittedKbps())
.diskUsage(convertDiskUsage(entry.getDiskUsage()))
.guestDiskUsage(convertGuestUsage(entry.getGuestDiskUsage()))
);
}
protected List<DiskUsage> convertDiskUsage(List<DiskUsageMetadata> list) {
return
map(list, metadata ->
new DiskUsage()
.id(metadata.getId())
.capacityMB(metadata.getCapacityMB())
);
}
protected List<GuestUsage> convertGuestUsage(List<GuestUsageMetadata> list) {
return
map(list, metadata ->
new GuestUsage()
.path(metadata.getPath())
.capacityMB(metadata.getCapacityMB())
.consumedMB(metadata.getConsumedMB())
);
}
protected synchronized void collectStats(Map<String, List<MonitoringEntry>> plainGrouping,
String key,
List<SamplingEntry> stats,
boolean distinct) {
if (!plainGrouping.containsKey(key)) {
plainGrouping.put(key, convertEntry(stats));
return;
}
if (!distinct) {
plainGrouping.get(key).addAll(convertEntry(stats));
}
}
protected List<ServerMonitoringStatistics> selectServersStatsDistinct(
Map<Group, List<ServerMonitoringStatistics>> stats) {
Map<String, ServerMonitoringStatistics> distinctMap = new HashMap<>();
stats
.values()
.stream()
.flatMap(List::stream)
.forEach(stat -> {
if (!distinctMap.containsKey(stat.getName())) {
distinctMap.put(stat.getName(), stat);
}
});
return new ArrayList<>(distinctMap.values());
}
@SuppressWarnings("unchecked")
protected <T> MonitoringStatsEntry createMonitoringStatsEntry(T metadata, List<MonitoringEntry> entries) {
return new MonitoringStatsEntry<>(metadata, entries);
}
@SuppressWarnings("unchecked")
protected List<MonitoringStatsEntry> aggregate(List<MonitoringStatsEntry> plainEntries) {
return
plainEntries
.stream()
.map(entry -> {
List<OffsetDateTime> timestamps =
((List<OffsetDateTime>) entry
.getStatistics()
.stream()
//select distinct timestamps
.map(e -> ((MonitoringEntry) e).getTimestamp())
.distinct()
.collect(toList()));
List<MonitoringEntry> resultEntries =
timestamps
.stream()
.map(time -> aggregateMonitoringEntry(entry, time))
.collect(toList());
return new MonitoringStatsEntry(entry.getEntity(), resultEntries);
})
.collect(toList());
}
@SuppressWarnings("unchecked")
private MonitoringEntry aggregateMonitoringEntry(MonitoringStatsEntry entry, OffsetDateTime time) {
Supplier<Stream<MonitoringEntry>> streamSupplier =
() -> entry.getStatistics().stream()
.filter(e -> ((MonitoringEntry) e).getTimestamp().equals(time));
long entriesCount = streamSupplier.get().count();
return new MonitoringEntry()
.timestamp(time)
.cpu(
streamSupplier.get().collect(summingInt(MonitoringEntry::getCpu)))
.cpuPercent(
streamSupplier.get().collect(summingDouble(MonitoringEntry::getCpuPercent)) / entriesCount)
.diskUsageTotalCapacityMB(
streamSupplier.get().collect(summingInt(MonitoringEntry::getDiskUsageTotalCapacityMB)))
.memoryMB(
streamSupplier.get().collect(summingInt(MonitoringEntry::getMemoryMB)))
.memoryPercent(
streamSupplier.get().collect(summingDouble(MonitoringEntry::getMemoryPercent)) / entriesCount)
.networkReceivedKBps(
streamSupplier.get().collect(summingDouble(MonitoringEntry::getNetworkReceivedKBps)))
.networkTransmittedKBps(
streamSupplier.get().collect(summingDouble(MonitoringEntry::getNetworkTransmittedKBps)))
.diskUsage(aggregateDiskUsage(
streamSupplier.get().map(MonitoringEntry::getDiskUsage).flatMap(List::stream).collect(toList())))
.guestDiskUsage(aggregateGuestUsage(
streamSupplier.get().map(MonitoringEntry::getGuestDiskUsage).flatMap(List::stream).collect(toList())));
}
private List<DiskUsage> aggregateDiskUsage(List<DiskUsage> flatList) {
Map<String, List<DiskUsage>> map = new ConcurrentHashMap<>();
flatList.stream()
.forEach(item -> {
String id = item.getId();
if (map.get(id) == null) {
map.put(id, new ArrayList<>());
}
map.get(id).add(new DiskUsage().id(id).capacityMB(item.getCapacityMB()));
});
return
map
.keySet()
.stream()
.map(key ->
new DiskUsage()
.id(key)
.capacityMB(
map
.get(key)
.stream()
.collect(summingInt(DiskUsage::getCapacityMB))
)
)
.collect(toList());
}
private List<GuestUsage> aggregateGuestUsage(List<GuestUsage> flatList) {
Map<String, List<GuestUsage>> map = new HashMap<>();
flatList.stream()
.forEach(item -> {
if (map.get(item.getPath()) == null) {
map.put(item.getPath(), new ArrayList<>());
}
map.get(item.getPath()).add(
new GuestUsage()
.path(item.getPath())
.capacityMB(item.getCapacityMB())
.consumedMB(item.getConsumedMB())
);
});
return
map
.keySet()
.stream()
.map(key ->
new GuestUsage()
.path(key)
.capacityMB(map.get(key).stream().collect(summingInt(GuestUsage::getCapacityMB)))
.consumedMB(map.get(key).stream().collect(summingInt(GuestUsage::getConsumedMB)))
)
.collect(toList());
}
}